<?php
/**
 * Created by PhpStorm.
 * User: ycbwl
 * Date: 2018/10/27
 * Time: 1:08 PM
 */
namespace app\api\service;

use app\api\model\User;
use app\lib\exception\TokenException;
use app\lib\exception\WxException;
use think\Exception;
use think\facade\Cache;

class UserToken extends Token{

    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    function __construct($code)
    {
        $this->code = $code;
        $this->wxAppID = config('wx.app_id');
        $this->wxAppSecret = config('wx.app_secret');
        $this->wxLoginUrl = sprintf(config('wx.login_url'),$this->wxAppID,$this->wxAppSecret,$this->code);
    }

    public function get(){
        $result = curl($this->wxLoginUrl,'','GET');

        $wxResult = json_decode($result,true);
        if(empty($wxResult)){
            throw new Exception('获取session_key及openID时异常，微信内部错误！');
        }else{
            $loginFail = array_key_exists('errcode',$wxResult);
            if($loginFail){
                $this->processLoginError($wxResult);
            }else{
               return  $this->grantToken($wxResult);
            }
        }
    }


    private function grantToken($wxResult){
        //拿到openID
        //数据库查询opneid 是否存在 。。。
        //最终写入令牌缓存，返回token
        //key：令牌
        //value: wxResult,uid,scope(权限--作用域)
        $openid = $wxResult['openid'];
        $user = User::getByOpenID($openid);
        if($user){
            $uid = $user->id;
        }else{
            $uid = $this->newUser($openid);
        }
        $cacheValue = $this->prepareCachedValue($wxResult,$uid);
        $token = $this->saveToCache($cacheValue);
        return $token;

    }


    private function saveToCache($cacheValue){
        $key = self::generateToken();
        $value = json_encode($cacheValue);
        $expire_in = config("setting.token_expire_in");
        $result = Cache::set($key,$value,$expire_in);
        if(!$result){
            throw new TokenException([
                'msg'=>'服务器缓存异常！',
                'errorCode'=>10005
            ]);
        }
        return $key;
    }


    private function prepareCachedValue($wxResult,$uid){
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        $cachedValue['scope'] = 16;
        return $cachedValue;
    }


    private function newUser($openid){
        $user = User::create([
            'openid'=>$openid
        ]);
        return $user->id;
    }


    private function processLoginError($wxResult){
        throw new WxException([
            'msg'=>$wxResult['errmsg'],
            'errorCode'=>$wxResult['errcode']
        ]);
    }
}